
`include "common_header.verilog"

//  *************************************************************************
//  File : register_map_xl
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized reproduction or use is expressly prohibited. 
//  Copyright (c) 2014 MorethanIP
//  Muenchner Strasse 199, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  http://www.morethanip.com
//  *************************************************************************
//  Designed by : Daniel Koehler
//  info@morethanip.com
//  *************************************************************************
//  Description : Statistic / Configuration Registers for 40G MAC, credit based FIFOs
//  Version     : $Id: register_map_xl.v,v 1.7 2016/08/09 12:21:30 dp Exp $
//  *************************************************************************

module register_map_xl (

   reset_rxclk,
   reset_txclk,
   reset_ff_tx_clk,
   reset_ff_rx_clk,
   ff_tx_clk,
   ff_rx_clk,
   reset_reg_clk,
   rxclk,
   rxclk_ena,
   txclk,
   txclk_ena,
   reg_clk,
   reg_rd,
   reg_wr,
   reg_sel,
   reg_data_in,
   reg_data_out,
   rst_status,
   rx_section_empty,
   rx_section_full,
   tx_section_empty,
   tx_section_full,
   loc_fault,
   rem_fault,
   li_fault,
   tx_isidle,
   tx_empty_st,
   rx_empty_st,
   phy_los,
   mac_mode,
   tx_ipg_length,
   tx_ipg_comp_cnt,
   mac_addr,
   tx_addr_ins,
   tx_pad_en,
   promis_en,
   frm_length_max,
   tx_mtu,
   pad_en,
   crc_fwd,
   pause_fwd,
   rx_pause_bypass,
   pause_ignore,
   cmd_frm_ena,
   force_send_idle,
   rx_err_frm_disc,
   rx_short_disc,
   enable_tx,
   enable_rx,
   loop_ena,
   phy_txena,
   no_lgth_check,
   col_cnt_ext,
   sfd_any,
   tx_flush,
   xgmii_mode,
   lowp_ena,
   reg_lowp_int,
   reg_lowp,
   pfc_mode,
   pause_pfc_cmptbl,
   disable_flt_hdl,
   cl_pause_quanta,
   cl_pause_thresh,
   qmodeidle8x,
`ifdef MTIPM10_SWRST_CMPTBL
   rx_sw_reset,
   rx_sw_reset_done,
   tx_sw_reset,
   tx_sw_reset_done,
`else
   rx_credit_max,
   rx_credit_reset,
   rx_credit_reset_done,
   rx_credit,
`endif
   sw_reset,
   tx_pause_on,
   tx_ts_val,
   tx_ts_frm_out,
   tx_ts,
   reg_ts_avail,
`ifdef MTIPMAC_1SIF
   os_enable,
`endif
   hash_tab,
   mdio_data_out,
   mdio_busy_trans,
   sgpcs_data_out,
   stat_data_out);

`include "mtip_40geth_pack_package.verilog"

input   reset_rxclk;                            //  Asynchronous Reset - rx_clk Domain
input   reset_txclk;                            //  Asynchronous Reset - tx_clk Domain
input   reset_ff_tx_clk;                        //  Asynchronous Reset - ff_tx_clk Domain
input   reset_ff_rx_clk;                        //  Asynchronous Reset - ff_rx_clk Domain
input   ff_tx_clk;                              //  Transmit Local Clock        
input   ff_rx_clk;                              //  Receive Local Clock
input   reset_reg_clk;                          //  Asynchronous Reset - reg_clk Domain
input   rxclk;                                  //  xgmii rx Clock
input   rxclk_ena;                              //  xgmii rx Clock Enable
input   txclk;                                  //  xgmii tx Clock
input   txclk_ena;                              //  xgmii tx Clock Enable
input   reg_clk;                                //  ReferenceInterface Clock
input   reg_rd;                                 //  Register Read Strobe
input   reg_wr;                                 //  Register Write Strobe
input   [7:0] reg_sel;                          //  Register Address
input   [31:0] reg_data_in;                     //  Write Data for Host Bus
output  [31:0] reg_data_out;                    //  Read Data to Host Bus
input   rst_status;                             //  Reset Status Register
output  [ING_ADDR - 1:0] rx_section_empty;      //  Receive Section Empty - Pause Frame Generation Threshold 
output  [ING_ADDR - 1:0] rx_section_full;       //  Receive Section Full - FIFO Status 
output  [EG_ADDR - 1:0] tx_section_empty;       //  Transmit Section Empty - FIFO Status
output  [EG_ADDR - 1:0] tx_section_full;        //  Transmit Section Full - MAC Tx Start            
input   loc_fault;                              //  RX receives LF sequences
input   rem_fault;                              //  RX receives RF sequences        
input   li_fault;                               //  RX receives LinkInterruption sequences
input   tx_isidle;                              //  Transmit Statemachine is in IDLE
input   tx_empty_st;                            //  TX FIFO empty (data+status)
input   rx_empty_st;                            //  RX FIFO empty (data+status)
input   phy_los;                                //  PHY Loss of Signal Indication
output  mac_mode;                               //  WAN mode
output  [6:0] tx_ipg_length;                    //  WAN/LAN mode IPG setting. STANDARD=12 (for both modes)
output  [15:0] tx_ipg_comp_cnt;                 //  IPG compensation count
output  [47:0] mac_addr;                        //  Device Ethernet MAC address
output  tx_addr_ins;                            //  Insert MAC Source Address
output  tx_pad_en;                              //  Transmit Padding Enable
output  promis_en;                              //  Enable promiscuous mode: accept any frame 
output  [15:0] frm_length_max;                  //  Maximum Received Frame length		
output  [15:0] tx_mtu;                          //  Maximum Frame length for TX (statistics)
output  pad_en;                                 //  Enable Padding
output  crc_fwd;                                //  Forward Frames with CRC to Application
output  pause_fwd;                              //  Forward Pause Frames to Application
output  rx_pause_bypass;                        //  if 1 the pause frame removal datapath function is bypassed 
output  pause_ignore;                           //  Ignore Pause Frames Quantas
output  cmd_frm_ena;                            //  Enable Command Frames
output  force_send_idle;                        //  force Idle send
output  rx_err_frm_disc;                        //  Discard Received Errored Frames
output  rx_short_disc;                          //  Discard Received short frames (within FIFO)
output  lowp_ena;                               //  Enable Low Power Idle Generation
input   reg_lowp_int;                           //  Low Power Indication from MAC - local (rx_clk)
output  reg_lowp;                               //  Low Power Indication out to toplevel (reg_clk)
output  enable_tx;                              //  Enable Tx Path 	
output  enable_rx;                              //  Enable Rx Path
output  loop_ena;                               //  PHY Loopback Enable
output  phy_txena;                              //  PHY Transmit Enable
output  no_lgth_check;                          //  Disable Length Field Check 
output  col_cnt_ext;                            //  Extend COL_CNT in Link Fault SM
output  sfd_any;                                //  allow any SFD character
output  tx_flush;                               //  Flush egress pipeline
output  xgmii_mode;                             //  XGMII mode enable (0=XLGMII, 1=XGMII)
output  pfc_mode;                               //  Priority Flow Control (Class Based Pause) enable
output  pause_pfc_cmptbl;                       //  Link Pause Compatibility with PFC mode enable
output  disable_flt_hdl;                        //  if '1', RX RS does not affect TX data path
output  [8 * 16 - 1:0] cl_pause_quanta;         //  Class 0..7 PFC Quanta value
output  [8 * 16 - 1:0] cl_pause_thresh;         //  Threshold for Class 0..7 Refresh PFC Frame
output  qmodeidle8x;                            //  consider clock-enable during IDLE to be 8x faster (i.e. byte clock instead word clock)
`ifdef MTIPM10_SWRST_CMPTBL
output  rx_sw_reset;                            //  FIFO sync reset (ff_rx_clk)
input   rx_sw_reset_done;                       //  FIFO reset completed, pulse (ff_rx_clk)
output  tx_sw_reset;                            //  FIFO sync reset (ff_tx_clk)
input   tx_sw_reset_done;                       //  FIFO reset completed, pulse (ff_tx_clk)
`else
output  [7:0] rx_credit_max;                    //  credit counter init/max value (ff_rx_clk)
output  rx_credit_reset;                        //  FIFO reset (ff_rx_clk)
input   rx_credit_reset_done;                   //  FIFO reset completed, pulse (ff_rx_clk)
input   [7:0] rx_credit;                        //  current credit counter value (ff_rx_clk)
`endif
output  sw_reset;                               //  FIFO sync reset (reg_clk)
input   [7:0] tx_pause_on;                      //  per class pause condition
input   tx_ts_val;                              //  timestamp valid
input   tx_ts_frm_out;                          //  store timestamp
input   [31:0] tx_ts;                           //  transmit timestamp
output  reg_ts_avail;                           //  ts_avail status bit
`ifdef MTIPMAC_1SIF
output  os_enable;                              //  enable 1-step datapath functions (reg_clk)
`endif
output  [63:0] hash_tab;                        //  Hash table
input   [15:0] mdio_data_out;                   //  Data from MDIO module
input   mdio_busy_trans;                        //  MDIO transaction is currently ongoing
input   [15:0] sgpcs_data_out;                  //  Data from SGMII PCS module
input   [31:0] stat_data_out;                   //  Data from Statistics module

reg     [31:0] reg_data_out; 
wire    [ING_ADDR - 1:0] rx_section_empty; 
wire    [ING_ADDR - 1:0] rx_section_full; 
wire    [EG_ADDR - 1:0] tx_section_empty; 
wire    [EG_ADDR - 1:0] tx_section_full; 
wire    mac_mode;
wire    [6:0] tx_ipg_length; 
wire    [15:0] tx_ipg_comp_cnt;
wire    [47:0] mac_addr; 
wire    tx_addr_ins; 
wire    tx_pad_en; 
wire    promis_en; 
wire    [15:0] frm_length_max; 
reg     [15:0] tx_mtu;
wire    pad_en; 
wire    crc_fwd; 
wire    pause_fwd; 
wire    pause_ignore; 
wire    cmd_frm_ena; 
wire    force_send_idle; 
wire    rx_err_frm_disc; 
wire    rx_short_disc;
wire    lowp_ena;
wire    reg_lowp;
reg     enable_tx; 
reg     enable_rx; 
wire    loop_ena; 
wire    phy_txena; 
wire    no_lgth_check; 
wire    col_cnt_ext; 
wire    sfd_any;
wire    tx_flush;
wire    xgmii_mode;
wire    pfc_mode; 
wire    pause_pfc_cmptbl; 
wire    disable_flt_hdl;
wire    [8 * 16 - 1:0] cl_pause_quanta; 
wire    [8 * 16 - 1:0] cl_pause_thresh; 
wire    qmodeidle8x;
`ifdef MTIPM10_SWRST_CMPTBL
wire    rx_sw_reset;
wire    tx_sw_reset;
`else
wire    [7:0] rx_credit_max; 
wire    rx_credit_reset; 
`endif
wire    sw_reset; 
wire    reg_ts_avail;
`ifdef MTIPMAC_1SIF
wire    os_enable;
`endif
wire    [63:0] hash_tab;

//  Registers
//  --------------
reg     [31:0] scratch; 
wire    [31:0] command_config; 
reg     command_config0; 
reg     command_config1; 
reg     [19:3] command_config19_3; 
reg     command_config20; 
reg     command_config21; 
reg     command_config22;
reg     command_config23; 
reg     command_config24; 
reg     command_config25; 
`ifdef MTIPM10_SWRST_CMPTBL
reg     command_config26;         // TX FIFO reset
`endif
reg     command_config27;         // Disable Fault Handling
reg     [31:0] mac_0; 
reg     [15:0] mac_1; 
reg     [31:0] frm_length_max_reg; 
reg     [31:0] rx_section_reg; 
reg     [31:0] tx_section_reg; 
reg     [8:0] status_reg; 
reg     [6:0] tx_ipg_length_reg; 
reg     [15:0] tx_ipg_comp_cnt_reg;
`ifdef MTIPM10_SWRST_CMPTBL
wire    tx_sw_reset_done_sy;                    // tx_sw_reset_done sync'ed to reg_clk
`else
reg     credit_trigger_reg; 
reg     [7:0] init_credit_reg; 
wire    rx_credit_reset_done_sy;                //  rx reset completed
`endif
reg     [7:0] cl_pause_wrbit;     //  one bit per register for cl_pause_quanta/thres_reg writes to reduce load on reg_sel (timing)
reg     [8 * 16 - 1:0] cl_pause_quanta_reg;     //  Class 0..7 PFC Quanta value
reg     [8 * 16 - 1:0] cl_pause_thresh_reg;     //  Threshold for Class 0..7 Refresh PFC Frame
wire    [7:0] tx_pause_on_reg;                  //  per class pause condition
wire    [31:0] hash_reg; 
reg     [63:0] hash_tab_reg; 
reg     xgmii_mode_reg;
reg     qmodeidle8x_reg;                        //  consider clock-enable during IDLE to be 8x faster (i.e. byte clock instead word clock)
`ifdef MTIPMAC_1SIF
reg     os_enable_reg;                          //  enable 1-step datapath functions
`endif
reg     rx_pause_bypass_reg;
//  Statistics
//  ----------

wire    sw_reset_done_int; 

//  timestamp latch
wire    tx_ts_val_in;                           //  input pulse
reg     [31:0] tx_ts_l;                         //  latched value
wire    tx_ts_val_in_sy;                        //  input pulse in reg_clk domain

//  local
//  -----

wire    loc_fault_sy;                           //  RX receives LF sequences (sync'ed to reg_clk)
wire    rem_fault_sy;                           //  RX receives RF sequences (sync'ed to reg_clk)
wire    li_fault_sy;                            //  RX receives LinkInterruption sequences
wire    tx_isidle_sy;                           //  Transmit Statemachine is in IDLE
wire    tx_empty_st_sy;                         //  TX FIFO empty (data+status)
wire    rx_empty_st_sy;                         //  RX FIFO empty (data+status)
wire    reg_lowp_int_sy;                        //  Low Power Idle (sync'ed to reg_clk)
wire    phy_los_sy;                             //  PHY Loss of Signal Indication (sync'ed to reg_clk)
wire    sw_reset_int; 
reg     hash_wren; 
reg     hash_wdata; 
reg     [5:0] hash_waddr; 
reg     hash_rdata; 

//  Scratch Test Register
//  ---------------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_1
   if (reset_reg_clk == 1'b 1)
      begin
      scratch <= {32{1'b 0}};	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 01)
         begin
         scratch <= reg_data_in;	
         end
      end
   end

//  Command Configuration Register
//  ------------------------------

assign command_config[31:28] = {4{1'b 0}};
assign command_config[27]    = command_config27;
`ifdef MTIPM10_SWRST_CMPTBL
assign command_config[26]    = command_config26;
`else
assign command_config[26]    = 1'b 0;
`endif
assign command_config[25]    = command_config25;
assign command_config[24]    = command_config24;
assign command_config[23]    = command_config23;
assign command_config[22]    = command_config22;
assign command_config[21]    = command_config21;
assign command_config[20]    = command_config20; 
assign command_config[19:3]  = command_config19_3[19:3]; 
assign command_config[2]     = 1'b 0; 
assign command_config[1:0]   = {command_config1, command_config0}; 

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_2
   if (reset_reg_clk == 1'b 1)
      begin
      command_config0           <= 1'b 0;	
      command_config1           <= 1'b 0;	
      command_config19_3[19:12] <= {8{1'b 0}};	
      command_config19_3[11]    <= 1'b 1;       // tx_pad_en
      command_config19_3[10:3]  <= {8{1'b 0}};	
      command_config20          <= 1'b 0;	
      command_config21          <= 1'b 0;	
      command_config22          <= 1'b 0;
      command_config23          <= 1'b 0;	
      command_config24          <= 1'b 0;	
      command_config25          <= 1'b 0;	
    `ifdef MTIPM10_SWRST_CMPTBL
      command_config26          <= 1'b 0;
    `endif
      command_config27          <= 1'b 0;
      end
   else
      begin
//  Self-Clearing Reset
//  -------------------
      if (reg_wr == 1'b 1 & reg_sel == 8'h 02)
         begin
         command_config19_3[12] <= reg_data_in[12];	
         end
      else if (sw_reset_done_int == 1'b 1 )
         begin
//  Disable After Software Reset
//  ----------------------------
         command_config19_3[12] <= 1'b 0;	
         end
//  Core Configuration
//  ------------------
      if (reg_wr == 1'b 1 & reg_sel == 8'h 02)
         begin
         command_config27          <= reg_data_in[27];
         command_config25          <= reg_data_in[25];
         command_config24          <= reg_data_in[24];
         command_config23          <= reg_data_in[23];
         command_config22          <= reg_data_in[22];	
         command_config21          <= reg_data_in[21];	
         command_config20          <= reg_data_in[20];	
         command_config19_3[19:13] <= reg_data_in[19:13];	
         command_config19_3[11:3]  <= reg_data_in[11:3];	
         command_config1           <= reg_data_in[1];	
         command_config0           <= reg_data_in[0];	
         end

    `ifdef MTIPM10_SWRST_CMPTBL
      //  Self Clearing TX FIFO reset
      //  ---------------------------
      if (reg_wr == 1'b 1 & reg_sel == 8'h 02)
         begin
         command_config26 <= reg_data_in[26];
         end
      else if( tx_sw_reset_done_sy == 1'b 1 )
         begin
         command_config26 <= 1'b 0;
         end         
    `endif

      end
   end

//  ---------------------- --

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_3
   if (reset_reg_clk == 1'b 1)
      begin
      enable_tx <= 1'b 0;	
      enable_rx <= 1'b 0;	
      end
   else
      begin
      enable_tx <= command_config0;	
      enable_rx <= command_config1;	
      end
   end

assign mac_mode         = command_config19_3[3];
assign promis_en        = command_config19_3[4]; 
assign pad_en           = ENA_RX_PAD_REM ? command_config19_3[5] : 1'b 0;
assign crc_fwd          = command_config19_3[6]; 
assign pause_fwd        = command_config19_3[7]; 
assign pause_ignore     = command_config19_3[8]; 
assign tx_addr_ins      = command_config19_3[9]; 
assign loop_ena         = command_config19_3[10]; 
assign tx_pad_en        = command_config19_3[11]; 
assign sw_reset_int     = command_config19_3[12]; 
assign cmd_frm_ena      = command_config19_3[13]; 
assign rx_err_frm_disc  = command_config19_3[14]; 
assign phy_txena        = command_config19_3[15]; 
assign force_send_idle  = command_config19_3[16]; 
assign no_lgth_check    = command_config19_3[17]; 
assign col_cnt_ext      = command_config19_3[18]; 
assign pfc_mode         = command_config19_3[19]; 
assign pause_pfc_cmptbl = command_config20; 
assign sfd_any          = command_config21;
assign tx_flush         = command_config22;
assign lowp_ena         = command_config23;
//assign xxx            = command_config24;   // mask reg_lowp with rx fifo empty, see below
assign rx_short_disc    = command_config25;
assign disable_flt_hdl  = command_config27;

//  MAC Address
//  -----------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_4
   if (reset_reg_clk == 1'b 1)
      begin
      mac_0 <= {32{1'b 0}};	
      mac_1[15:0] <= {16{1'b 0}};	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 03)
         begin
         mac_0 <= reg_data_in;	
         end
      if (reg_wr == 1'b 1 & reg_sel == 8'h 04)
         begin
         mac_1[15:0] <= reg_data_in[15:0];	
         end
      end
   end

assign mac_addr[47:32] = mac_1; 
assign mac_addr[31:0]  = mac_0; 

//  Maximum Frame Length
//  --------------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_5
   if (reset_reg_clk == 1'b 1)
      begin
      frm_length_max_reg <= 32'h 0600;	
      tx_mtu             <= 16'h 0000;
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 05)
         begin
         frm_length_max_reg <= reg_data_in;	
         end
         
        // create a TX MTU value. Stay backward compatible when upper 16 bits are not written
   	
   	if( (|frm_length_max_reg[31:16])==1'b 0 )
   	begin
   	        // not set, copy the rx configuration 
   		tx_mtu <= frm_length_max_reg[15:0];
        end
        else
        begin
   		tx_mtu <= frm_length_max_reg[31:16];
        end         
         
      end
   end

assign frm_length_max = frm_length_max_reg[15:0]; 

//  FIFO Thresholds
//  ---------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_7
   if (reset_reg_clk == 1'b 1)
      begin
      rx_section_reg[31:16] <= 16'h 0000;	
      rx_section_reg[15:0]  <= 16'h 0008;	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 07)
         begin
         rx_section_reg <= reg_data_in;	
         end
      end
   end

assign rx_section_full = rx_section_reg[ING_ADDR - 1:0]; 
assign rx_section_empty = rx_section_reg[16 + ING_ADDR - 1:16]; 
// 
always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_8
   if (reset_reg_clk == 1'b 1)
      begin
      tx_section_reg[31:16] <= 16'h 0000;	
      tx_section_reg[15:0]  <= 16'h 0008;	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 08)
         begin
         tx_section_reg <= reg_data_in;	
         end
      end
   end

assign tx_section_full  = tx_section_reg[EG_ADDR - 1:0]; 
assign tx_section_empty = tx_section_reg[16 + EG_ADDR - 1:16]; 

//  HASH Table Write
//  ----------------
always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_9
   if (reset_reg_clk == 1'b 1)
      begin
      hash_tab_reg <= {64{1'b 0}};	
      hash_wren    <= 1'b 0;	
      hash_wdata   <= 1'b 0;	
      hash_waddr   <= {6{1'b 0}};	
      hash_rdata   <= 1'b 0;	
      end
   else
      begin
      if (reg_sel == 8'h 0b)
         begin
         hash_wdata <= reg_data_in[8];	//  Bit 8 is data bit to write
         hash_waddr <= reg_data_in[5:0];	
         end

      if (reg_wr == 1'b 1 & reg_sel == 8'h 0b)
         begin
         hash_wren <= 1'b 1;	
         end
      else
         begin
         hash_wren <= 1'b 0;	
         end

        //  write bit into Table

      if (hash_wren == 1'b 1)
         begin
         hash_tab_reg[hash_waddr] <= hash_wdata;	
         end

        //  read current content

      hash_rdata <= hash_tab_reg[hash_waddr];	//  current address is read 

      end
   end

assign hash_tab = hash_tab_reg; 
assign hash_reg = {20'h 00000, 3'b 000, hash_rdata, 2'b 00, hash_waddr}; 

//  MDIO Controller
//  ----------------
//  registers 12..15 (externally)

//  PHY STATUS
//  ----------
//  register 16: Read only


//  TX_IPG_LENGTH
//  -------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_10
   if (reset_reg_clk == 1'b 1)
      begin
      tx_ipg_length_reg[6:0] <= 7'd 12;	//  default to 12!
      tx_ipg_comp_cnt_reg <= {16{1'b 0}};
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 11)
         begin
         tx_ipg_length_reg[6:0] <= reg_data_in[6:0];	
         tx_ipg_comp_cnt_reg <= reg_data_in[31:16];
         end
      end
   end

assign tx_ipg_length = tx_ipg_length_reg[6:0]; 
assign tx_ipg_comp_cnt = tx_ipg_comp_cnt_reg;

//  global sync reset
assign sw_reset = sw_reset_int;

`ifdef MTIPM10_SWRST_CMPTBL

        // RX FIFO software reset
        redge_ckxing RXRES (
          .reset(reset_reg_clk),
          .clk(reg_clk),
          .sig(sw_reset_int),
          .reset_clk_o(reset_ff_rx_clk),
          .clk_o(ff_rx_clk),
          .sig_o(rx_sw_reset));

        // TX FIFO software reset
        mtip_xsync #(1) TXRES (
          .data_in(command_config26),
          .reset(reset_ff_tx_clk),
          .clk(ff_tx_clk),
          .data_s(tx_sw_reset));

        // done pulse back into reg clock domain
        redge_ckxing TXRDONESY (
          .reset(reset_ff_tx_clk),
          .clk(ff_tx_clk),
          .sig(tx_sw_reset_done),
          .reset_clk_o(reset_reg_clk),
          .clk_o(reg_clk),
          .sig_o(tx_sw_reset_done_sy));

`else

//  CreditTrigger
//  -------------

//  bring reset done pulse into reg_clk domain

redge_ckxing CRDSY (

          .reset(reset_ff_rx_clk),
          .clk(ff_rx_clk),
          .sig(rx_credit_reset_done),
          .reset_clk_o(reset_reg_clk),
          .clk_o(reg_clk),
          .sig_o(rx_credit_reset_done_sy));

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_11
   if (reset_reg_clk == 1'b 1)
      begin
      credit_trigger_reg <= 1'b 0;	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 12)
         begin
         credit_trigger_reg <= reg_data_in[0];	
         end
      else if (rx_credit_reset_done_sy == 1'b 1 )
         begin
         credit_trigger_reg <= 1'b 0;	
         end
      end
   end

//  bring reset request into ff_rx_clk domain

mtip_xsync #(1) CRES (

          .data_in(credit_trigger_reg),
          .reset(reset_ff_rx_clk),
          .clk(ff_rx_clk),
          .data_s(rx_credit_reset));

//  INIT_CREDIT value
//  -------------
always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_12
   if (reset_reg_clk == 1'b 1)
      begin
      init_credit_reg <= {8{1'b 0}};	
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 13)
         begin
         init_credit_reg <= reg_data_in[7:0];	
         end
      end
   end

assign rx_credit_max = init_credit_reg; //  clock domain crossing... (ff_rx_clk)

//  Credit_REG: read only current credit value
//  ------------------------------------------

`endif

//  PFC Pause Quanta/Threshold configurations
//  -----------------------------------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_13
   if (reset_reg_clk == 1'b 1)
      begin
      cl_pause_wrbit <= 8'h 00;
      cl_pause_quanta_reg <= {128{1'b 0}};	
      cl_pause_thresh_reg <= {128{1'b 0}};	
      end
   else
      begin
        // create a write strobe for each individual register at offset 21..27
        // to remove load from reg_sel and reduce logic on the 8 registers here.
        // Note that a write cycle is always at minimum 2 cycles and reg_data_in is stable.
        
        cl_pause_wrbit[0] <= (reg_wr == 1'b 1 & reg_sel == 8'h 15) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[1] <= (reg_wr == 1'b 1 & reg_sel == 8'h 16) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[2] <= (reg_wr == 1'b 1 & reg_sel == 8'h 17) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[3] <= (reg_wr == 1'b 1 & reg_sel == 8'h 18) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[4] <= (reg_wr == 1'b 1 & reg_sel == 8'h 19) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[5] <= (reg_wr == 1'b 1 & reg_sel == 8'h 1a) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[6] <= (reg_wr == 1'b 1 & reg_sel == 8'h 1b) ? 1'b 1 : 1'b 0;
        cl_pause_wrbit[7] <= (reg_wr == 1'b 1 & reg_sel == 8'h 1c) ? 1'b 1 : 1'b 0;

//  per class quanta
      if (cl_pause_wrbit[0]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 15)
         begin
         cl_pause_quanta_reg[31:0] <= reg_data_in;	
         end
      if (cl_pause_wrbit[1]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 16)
         begin
         cl_pause_quanta_reg[63:32] <= reg_data_in;	
         end
      if (cl_pause_wrbit[2]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 17)
         begin
         cl_pause_quanta_reg[95:64] <= reg_data_in;	
         end
      if (cl_pause_wrbit[3]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 18)
         begin
         cl_pause_quanta_reg[127:96] <= reg_data_in;	
         end

//  per class retransmit thresholds
      if (cl_pause_wrbit[4]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 19)
         begin
         cl_pause_thresh_reg[31:0] <= reg_data_in;	
         end
      if (cl_pause_wrbit[5]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 1a)
         begin
         cl_pause_thresh_reg[63:32] <= reg_data_in;	
         end
      if (cl_pause_wrbit[6]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 1b)
         begin
         cl_pause_thresh_reg[95:64] <= reg_data_in;	
         end
      if (cl_pause_wrbit[7]==1'b 1) // reg_wr == 1'b 1 & reg_sel == 8'h 1c)
         begin
         cl_pause_thresh_reg[127:96] <= reg_data_in;	
         end

      end
   end

assign cl_pause_quanta = cl_pause_quanta_reg; 
assign cl_pause_thresh = cl_pause_thresh_reg; 

//  TX is paused indication, RO
//  ---------------------------

mtip_xsync #(8) TPSSY (

          .data_in(tx_pause_on),
          .reset(reset_reg_clk),
          .clk(reg_clk),
          .data_s(tx_pause_on_reg));

//  TX Timestamp storage, RO
//  ------------------------

always @(posedge reset_txclk or posedge txclk)
   begin : process_14
   if (reset_txclk == 1'b 1)
      begin
      tx_ts_l <= {32{1'b 0}};	
      end
   else
      begin

//  latch time value in line clock domain
//  -------------------------------------

      if (tx_ts_val == 1'b 1 & tx_ts_frm_out == 1'b 1)
         begin
         tx_ts_l <= tx_ts;	
         end
      end
   end

assign tx_ts_val_in = tx_ts_val & tx_ts_frm_out; //  bring timestamp available pulse into reg-clock domain

redge_ckxing TSSY (

          .reset(reset_txclk),
          .clk(txclk),
          .sig(tx_ts_val_in),
          .reset_clk_o(reset_reg_clk),
          .clk_o(reg_clk),
          .sig_o(tx_ts_val_in_sy));

//  PHY Status Register
//  -------------------

mtip_xsync #(8) SSY (

          .data_in({tx_isidle, rx_empty_st, tx_empty_st, reg_lowp_int, loc_fault, rem_fault, li_fault, phy_los}),
          .reset(reset_reg_clk),
          .clk(reg_clk),
          .data_s({tx_isidle_sy, rx_empty_st_sy, tx_empty_st_sy, reg_lowp_int_sy, loc_fault_sy, rem_fault_sy, li_fault_sy, phy_los_sy}));

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_15
   if (reset_reg_clk == 1'b 1)
      begin
      status_reg <= {9{1'b 0}};	
      end
   else
      begin

        //  local fault latched,ROR

      if (loc_fault_sy == 1'b 1)
         begin
         status_reg[0] <= 1'b 1;	
         end
      else if (rst_status == 1'b 1 )
         begin
         status_reg[0] <= 1'b 0;	
         end

        //  remote fault latched, ROR

      if (rem_fault_sy == 1'b 1)
         begin
         status_reg[1] <= 1'b 1;	
         end
      else if (rst_status == 1'b 1 )
         begin
         status_reg[1] <= 1'b 0;	
         end
        //  LOS, static indication

      status_reg[2] <= phy_los_sy;	

        //  3: timestamp valid latch, clear when writing a 1 to the register.

      if (tx_ts_val_in_sy == 1'b 1)
         begin
         status_reg[3] <= 1'b 1;	
         end
      else if (reg_wr == 1'b 1 & reg_sel == 8'h 10 & reg_data_in[3] == 1'b 1 )
         begin
         status_reg[3] <= 1'b 0;	
         end
      
        //  4: low power idle receive
        
      status_reg[4] <= reg_lowp_int_sy;
      
        //  5: tx fifo all empty
        
      status_reg[5] <= tx_empty_st_sy;
      
        //  6: rx fifo all empty
        
      status_reg[6] <= rx_empty_st_sy;

        //  7: LinkInterruption fault latched, ROR

      if (li_fault_sy == 1'b 1)
         begin
         status_reg[7] <= 1'b 1;	
         end
      else if (rst_status == 1'b 1 )
         begin
         status_reg[7] <= 1'b 0;	
         end

        //  8: tx statemachine in idle
        
      status_reg[8] <= tx_isidle_sy;

      end
   end

assign reg_lowp     = reg_lowp_int_sy & (rx_empty_st_sy | ~command_config24);  // mask with fifo empty when cc24=1; in reg_clk domain
assign reg_ts_avail = status_reg[3];

//  Interface Mode Register
//  -------------------

always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_xgm
   if (reset_reg_clk == 1'b 1)
      begin
      xgmii_mode_reg <= 1'b 0;
      qmodeidle8x_reg <= 1'b 0;
        `ifdef MTIPMAC_1SIF
      os_enable_reg <= 1'b 0;
        `endif
        rx_pause_bypass_reg <= 1'b0;
      end
   else
      begin
      if (reg_wr == 1'b 1 & reg_sel == 8'h 20)
         begin
         xgmii_mode_reg <= reg_data_in[0];      // Set Clause49 XGMII
         // 3:1 reserved
         qmodeidle8x_reg <= reg_data_in[4];     // Assume GMII converter: then Pause Quanta Timer must consider 8x speedup
        `ifdef MTIPMAC_1SIF
         os_enable_reg <= reg_data_in[5];       //  enable 1-step datapath functions (reg_clk)
        `endif
        rx_pause_bypass_reg <=  reg_data_in[6];
         end
      end
   end

assign xgmii_mode = xgmii_mode_reg;
assign qmodeidle8x = qmodeidle8x_reg;
`ifdef MTIPMAC_1SIF
assign os_enable = os_enable_reg;
`endif
assign rx_pause_bypass = rx_pause_bypass_reg;
//  Output MUX
//  ----------
always @(posedge reset_reg_clk or posedge reg_clk)
   begin : process_16
   if (reset_reg_clk == 1'b 1)
      begin
      reg_data_out <= {32{1'b 0}};	
      end
   else
      begin
      if (reg_rd == 1'b 1)
         begin
         case (reg_sel)
         8'h 00:
            begin
            reg_data_out[7:0]   <= CORE_REVISION;
            reg_data_out[15:8]  <= CORE_VERSION;	
            reg_data_out[31:16] <= CUST_VERSION;	
            end
         8'h 01:
            begin
            reg_data_out <= scratch;	
            end
         8'h 02:
            begin
            reg_data_out <= command_config;	
            end
         8'h 03:
            begin
            reg_data_out <= mac_0;	
            end
         8'h 04:
            begin
            reg_data_out <= {16'h 0000, mac_1};	
            end
         8'h 05:
            begin
            reg_data_out <= frm_length_max_reg;	
            end
         8'h 06:
            begin
            reg_data_out <= {32'h 0};	
            end
         8'h 07:
            begin
            reg_data_out <= rx_section_reg;	
            end
         8'h 08:
            begin
            reg_data_out <= tx_section_reg;	
            end
         8'h 09:
            begin
            reg_data_out[15:0]  <= 16'h 0; // FIFO_THRESHOLD;	
            reg_data_out[31:16] <= 16'h 0; // FIFO_THRESHOLD;	
            end
         8'h 0a:
            begin
            reg_data_out[15:0]  <= 16'h 0; // FIFO_THRESHOLD;	
            reg_data_out[31:16] <= 16'h 0; // FIFO_THRESHOLD;	
            end
         8'h 0b:
            begin
            reg_data_out <= hash_reg;	//  HASH table read
            end
        // MDIO
         8'h 0c,
         8'h 0d,
         8'h 0e,
         8'h 0f:
            begin
            reg_data_out <= {mdio_busy_trans, 15'b 000000000000000, mdio_data_out};	
            end
         8'h 10:
            begin
            reg_data_out <= {23'h 0, status_reg};	
            end
         8'h 11:
            begin
            reg_data_out <= {tx_ipg_comp_cnt_reg, 8'h 0, 1'b 0, tx_ipg_length_reg};	
            end

    `ifdef MTIPM10_SWRST_CMPTBL

         8'h 12,
         8'h 13,
         8'h 14:
            begin
            reg_data_out <= {32{1'b 0}};   //  reserved
            end

    `else

         8'h 12:
            begin
            reg_data_out <= {28'h 0, 3'b 000, credit_trigger_reg};	
            end
         8'h 13:
            begin
            reg_data_out <= {24'h 0, init_credit_reg};	
            end
         8'h 14:
            begin
            reg_data_out <= {24'h 0, rx_credit};	//  clock domain crossing... (ff_rx_clk)
            end

    `endif

//  PFC
         8'h 15:
            begin
            reg_data_out <= cl_pause_quanta_reg[31:0];	
            end
         8'h 16:
            begin
            reg_data_out <= cl_pause_quanta_reg[63:32];	
            end
         8'h 17:
            begin
            reg_data_out <= cl_pause_quanta_reg[95:64];	
            end
         8'h 18:
            begin
            reg_data_out <= cl_pause_quanta_reg[127:96];	
            end
         8'h 19:
            begin
            reg_data_out <= cl_pause_thresh_reg[31:0];	
            end
         8'h 1a:
            begin
            reg_data_out <= cl_pause_thresh_reg[63:32];	
            end
         8'h 1b:
            begin
            reg_data_out <= cl_pause_thresh_reg[95:64];	
            end
         8'h 1c:
            begin
            reg_data_out <= cl_pause_thresh_reg[127:96];	
// 
            end
         8'h 1d:
            begin
            reg_data_out <= {24'h 0, tx_pause_on_reg};	
            end
         8'h 1e:
            begin
            reg_data_out <= {32{1'b 0}};	
            end
         8'h 1f:
            begin
            reg_data_out <= tx_ts_l;	
            end
         8'h 20:        // XIF_MODE
            begin
            reg_data_out <= {24'h 0, 
                             1'b 0,    // 7
                             rx_pause_bypass_reg,
                            `ifdef MTIPMAC_1SIF // 5
                            os_enable_reg,              
                            `else
                            1'b 0,
                            `endif 
                            qmodeidle8x_reg,    // 4
                            3'b 000,            // 3:1 reserved
                            xgmii_mode_reg};    // 0
            end

         8'h c0, 8'h c1, 8'h c2, 8'h c3, 8'h c4, 8'h c5, 8'h c6, 8'h c7,        // overlay PCS registers
         8'h c8, 8'h c9, 8'h ca, 8'h cb, 8'h cc, 8'h cd, 8'h ce, 8'h cf,
         8'h d0, 8'h d1, 8'h d2, 8'h d3, 8'h d4, 8'h d5, 8'h d6, 8'h d7,
         8'h d8, 8'h d9, 8'h da, 8'h db, 8'h dc, 8'h dd, 8'h de, 8'h df
         :
            begin
            reg_data_out <= {16'h 0000, sgpcs_data_out};	
            end

//  33..end: statistics
         default:
            begin
            reg_data_out <= stat_data_out;	
            end
         endcase
         end
      else
         begin
         reg_data_out <= {32{1'b 0}};	
         end
      end
   end                   

// delay the sw_reset for at least 1 clocks
// ----------------------------------------

mtip_xsync #(1) SWRESET_DELAY (

          .data_in(sw_reset_int),
          .reset(reset_reg_clk),
          .clk(reg_clk),
          .data_s(sw_reset_done_int));

endmodule // module register_map_xl
